#include "MovePart.h"
#include "Scene/Map.h"
#include "Scene/MapMgr.h"
#include "Common/Utility/ServerTime.h"
#include "teleporter/TeleporterInfoMgr.h"
#include "base/core/gamemath.h"
#include "Player.h"
#include "Character/monster/MonsterRefMgr.h"
#include "Character/monster/Monster.h"

#include "Character/buff/BuffEffectCfg.h"
#include <algorithm>
#include "PlayerMgr.h"
#include "Team/GTeamManager.h"
#include "base/core/Profiler.h"
#include "Common/TableDataEx/MapCfg.h"
#include "PlaneMgr/PlaneMgr.h"
#include "Common/AttrMgr/AttrMgr.h"
#include "Common/TableData/ConstantConstantCfg.h"
/*
位置校验点：
1.当前位置点
2.分段路径长
3.路径点是否合法
*/


const int g_constRockMoveDistance = 12;   //翻滚一次的最大距离，单位：米
const float g_constMoveMaxTime = 1;		//这里做个容错，最大距离为 0.5秒 一般200ms会同步一次，加上网络延迟，这里设置为2秒
const int g_constRockRollCDTime = 8;	//翻滚时间
const int g_constRockSpeed = 20;		//翻滚速度
MovePart::MovePart()
: m_enMovingFlag(enMovingFlag_None)
{
}

MovePart::~MovePart()
{
}

bool MovePart::Init(Creature *pMaster, uint32_t partType, CharacterDBInfo* pCharacterDB /* = nullptr */)
{
	Part::Init(pMaster, partType);
	m_StepStarttamp = 0;
	if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
		g_GetEvent()->Subscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_LEAVE_SCENE, m_pMaster->GetCid(), m_pMaster->CreatureKind(), NULL);

	//m_lastSpeed = m_pMaster->GetSpeed();
	m_fRockAngle = 0;
	m_fRockType = ActorRockerMove_Type_Up;
	m_enMovingFlag = enMovingFlag_None;
	m_lastMoveTime = 0;
	m_lastRockRollTime = 0;
	m_moveErrorNum = 0;
	m_isTeamFollow = false;
	m_moveSpeed = m_pMaster->GetSpeed();
	if (m_pMaster->CreatureKind() != CREATURE_PLAYER)
	{
		m_moveIntervalTime = 50;
	}
	else
	{
		m_moveIntervalTime = 50;
	}


	SetTimedo(TIMEID_CHEAT_MOVE, INTERVAL_MOVE_CHEAT_TIME);

	return true;
}

bool MovePart::UnInit()
{
	g_GetEvent()->UnSubscribe(dynamic_cast<IEventExecuteSink*>(this), EVENT_LEAVE_SCENE, m_pMaster->GetCid(), m_pMaster->CreatureKind());
	g_GetTimerAxis()->KillAllTimer(this);
	return true;
}

void MovePart::OnExecute(uint16_t nEventID, uint64_t nSrcID, uint8_t bySrcType, void *pContext, int32_t nLen)
{
	if (m_pMaster->IsDead())
	{
		return;
	}
	ActorMove moveData;
	switch (nEventID)
	{
	case EVENT_UNDER_ATTACK:
	{
		StopMove();
		break;
	}
	case EVENT_LEAVE_SCENE:
	{
		StopSelfMove();
		break;
	}
	//case EVENT_BEEN_SEE:
	//	BeenSeeMoving(pContext, nLen);
	//	break;
	default:
		break;
	}
}

bool MovePart::OnMsgHandle(uint32_t cmd, const char* data, uint32_t len)
{
	//隐身，只接受加载地图成功
	//if (!m_pMaster->IsCanBeSeen() && cmd != CLIENT_TO_LOGIC_SCENE_LOAD_SUCCESS)
	//{
	//	return false;
	//}

	switch (cmd)
	{
	case CLIENT_TO_LOGIC_CHARACTER_MOVE:
		C2Move(data, len);
		break;
	case CLIENT_TO_LOGIC_SCENE_TRANS:
		C2TransPlace(data, len);
		break;
	case CLIENT_TO_LOGIC_CHARACTER_SKILLMOVE:
		C2SkillMove(data, len);
		break;
	case CLIENT_TO_LOGIC_CHARACTER_ROCKER_MOVE:
		C2RockerMove(data, len);
		break;
	case CLIENT_TO_LOGIC_CHARACTER_POS_UPDATE:
		C2UpdatePos(data, len);
		break;
	case CLIENT_TO_LOGIC_TEAM_POS_UPDATE:
		break;
	case CLIENT_TO_LOGIC_SCENE_LOAD_SUCCESS:
		C2TransFinish(data, len);
		break;
	case CLIENT_TO_LOGIC_TEAM_MOVE:
		C2TeamMove(data, len);
		break;
	case CLIENT_TO_LOGIC_TEAM_ROCKER_MOVE:
		C2TeamRockMove(data, len);
		break;
	case CLIENT_TO_LOGIC_TEAM_TRANS:
		C2TeamTranScene(data, len);
		break;
	default:
		break;
	}
	return true;
}

bool MovePart::GetDstInfoFromC(uint32_t typeId, uint32_t instanceId, Point3<float>& dstPos, TransSceneTmpInfo& transTmpInfo)
{
	Scene *pScene = m_pMaster->GetScene();
	if (!pScene)
	{
		LogErrFmtPrint("[logic] MovePart::GetDstInfoFromC pScene == nullptr:%lu", m_pMaster->GetCid());
		return false;
	}
	TeleporterInfo *pTeleporter = nullptr;
	//校验传送合法性，以后在这里做处理
	switch (typeId)
	{
	case TransSceneReq_Type_TransPoint:
		pTeleporter = g_GetTeleporterInfoMgr()->GetTeleporterInfo(instanceId);
		if (nullptr == pTeleporter)
		{
			LogErrFmtPrint("MovePart::GetDstInfoFromC...nullptr == pTeleporter...cid:%lu, instanceId:%u ",m_pMaster->GetCid(),instanceId);
			return false;
		}
		transTmpInfo.dstPos = pTeleporter->GetDstStandIdPos();
		transTmpInfo.dstmapId   = pTeleporter->GetDstMapId();
		transTmpInfo.dstSceneId = pTeleporter->GetDstMapId();
		if (transTmpInfo.dstPos.length() <= 0)
		{
			LogErrFmtPrint("MovePart::GetDstInfoFromC...transTmpInfo.dstPos.length() <= 0...cid:%lu, instanceId:%u, dstmap:%u ", m_pMaster->GetCid(), instanceId,transTmpInfo.dstmapId);
			return false;
		}
		if (g_GetMapCfgMgr()->IsDynamic(transTmpInfo.dstmapId))
		{
			if (g_GetMapCfgMgr()->IsUnionHomeMap(transTmpInfo.dstmapId)) //工会驻地地图
			{
				if (m_pMaster->GetAttr(C_UNION_ID) <= 0 || m_pMaster->GetAttr(C_UNION_HOME_SCENE) <= 0)
				{
					LogErrFmtPrint("MovePart::GetDstInfoFromC...m_pMaster->GetAttr(C_UNION_ID) <= 0 || m_pMaster->GetAttr(C_UNION_HOME_SCENE) <= 0...cid:%lu, instanceId:%u, dstmap:%u,unionid:%u,unionhome:%u ", m_pMaster->GetCid(), instanceId, transTmpInfo.dstmapId,m_pMaster->GetAttr(C_UNION_ID),m_pMaster->GetAttr(C_UNION_HOME_SCENE));
					return false;
				}
				transTmpInfo.dstSceneId = m_pMaster->GetAttr(C_UNION_HOME_SCENE);
			}
			else
			{
				//动态地图只能在当前地图内传送
				if (transTmpInfo.dstmapId != pScene->GetMapId())
				{
					LogErrFmtPrint("MovePart::GetDstInfoFromC...transTmpInfo.dstmapId != pScene->GetMapId()...cid:%lu, instanceId:%u, dstmap:%u ,curmapid:%u ", m_pMaster->GetCid(), instanceId, transTmpInfo.dstmapId, pScene->GetMapId());
					return false;
				}
				//动态地图的场景要取玩家当前的场景
				transTmpInfo.dstSceneId = pScene->GetSceneId();
			}
		}
		break;
	case TransSceneReq_Type_Route:
		break;
	case TransSceneReq_Type_Test:
		transTmpInfo.dstPos = dstPos;
		transTmpInfo.dstSceneId = instanceId;
		break;
	case TransSceneReq_Type_Free:
		transTmpInfo.dstmapId = instanceId;
		transTmpInfo.dstPos = dstPos;
		transTmpInfo.dstSceneId = instanceId;
		break;
	case TransSceneReq_Type_Force:
	{
		const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
		if (pJailMapID && pScene->GetSceneId() == (uint32_t)pJailMapID->constantdata)
		{
			Point3<float> pos = g_GetMapLocationCfg()->GetNearRelivePos(pScene->GetSceneId(), m_pMaster->GetPos(), m_pMaster->GetAttr(C_CAMP_ID));
			//直接传送到该地图的复活点
			transTmpInfo.dstmapId = pScene->GetSceneId();
			transTmpInfo.dstPos = pos;
			transTmpInfo.dstSceneId = pScene->GetSceneId();
		}
		else
		{
			transTmpInfo.dstmapId = instanceId;
			transTmpInfo.dstPos = dstPos;
			transTmpInfo.dstSceneId = instanceId;
		}
	}
	break;
	default:
		break;
	}

	return true;
}

void MovePart::C2TransPlace(const char *data, uint32_t len)
{

	//请求传送前，先停止之前的移动相关信息
	StopSelfMove();
	TransSceneReq transInfo;
	if (!transInfo.ParseFromArray(data, len))
	{
		LogErrFmtPrint("[logic] MovePart::C2TransPlace TransSceneReq parse failed....%lu", m_pMaster->GetCid());
		return;
	}

	uint32_t srcSceneID = m_pMaster->GetSceneId();

	//LogErrFmtPrint("[logic] MovePart::C2TransPlace receve client TransSceneReq cid:%lu", m_pMaster->GetCid());
	Point3<float> dstPos;
	dstPos.x = transInfo.dstpos().x();
	dstPos.y = transInfo.dstpos().y();
	dstPos.z = transInfo.dstpos().z();
	TransSceneTmpInfo transTmp;
	if (GetDstInfoFromC(transInfo.typeid_(), transInfo.instanceid(), dstPos, transTmp))
	{

		//不能让玩家手动点传送到流放之地 
		const ConstantConstantCfgInfo *pJailMapID = g_GetConstantConstantCfgTable()->GetConstantConstantCfgInfo(EArg_ClearPoint_Jail);
		if (pJailMapID && srcSceneID != (uint32_t)pJailMapID->constantdata && transTmp.dstSceneId == (uint32_t)pJailMapID->constantdata)
		{

			TransSceneRsp transRsp;
			transRsp.set_retcode(RET_CANTOT_TRANCE_TO_JAIL);
			g_GetLogicService()->SendDataToClient(m_pMaster->GetCid(), EMODULE_ID_MOVE, LOGIC_TO_CLIENT_TRANS_FAIL, &transRsp);
			return ;
		}

		//LogErrFmtPrint("[logic] MovePart::C2TransPlace  cid:%lu, cursceneid:%u, mapid:%u , dstsceneid:%u,dstmapid:%u ", m_pMaster->GetCid(), m_pMaster->GetSceneId(), m_pMaster->GetMapId(), transTmp.dstSceneId, transTmp.dstmapId);
		STransParam transParam;
		transParam.srcMapId = m_pMaster->GetMapId();
		transParam.transType = ETransType_Scene;
		if (!TransScene(transTmp.dstSceneId, transTmp.dstPos, transTmp.dstmapId, transParam))
		{
			//通知前端切场景失败
			TransSceneRsp transRsp;
			transRsp.set_retcode(RET_FAIL);

			//这一些要移到cantran中判断，给返回值 todo .. add by wangxx
			Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
			if (pPlayer)
			{
				if (pPlayer->InSonOfKillingStatus())
					transRsp.set_retcode(RET_ACTIVITY_SONOFKILLING_TRANS_ERROR);
				if (pPlayer->InWorldBossStatus())
					transRsp.set_retcode(RET_ACTIVITY_WORLD_BOSS_TRANS_ERROR);

				if (pPlayer->GetPkKillingValue()>0 && pJailMapID && pPlayer->GetSceneId() == (uint32_t)pJailMapID->constantdata)
					transRsp.set_retcode(RET_CANTOT_TRANCE_FROM_JAIL);
			}

			g_GetLogicService()->SendDataToClient(m_pMaster->GetCid(), EMODULE_ID_MOVE, LOGIC_TO_CLIENT_TRANS_FAIL, &transRsp);
			return;
		}

		// 如果是从流放之地到外面的，需要切到和平模式
		if (pJailMapID && (uint32_t)pJailMapID->constantdata == srcSceneID && (uint32_t)pJailMapID->constantdata != transTmp.dstSceneId)
		{
			PvpPart * pPart = dynamic_cast<PvpPart*>(m_pMaster->GetPart(PART_PVP));
			if (pPart)
			{
				pPart->SetPkMode(PK_MODE_CAMP);
			}
		}
	}
	else
	{
		TransSceneRsp transRsp;
		transRsp.set_retcode(RET_SCENE_NOT_TRANSPORT_INFO);
		g_GetLogicService()->SendDataToClient(m_pMaster->GetCid(), EMODULE_ID_MOVE, LOGIC_TO_CLIENT_TRANS_FAIL, &transRsp);
	}
	
}

bool MovePart::MoveTo(Point3<float>& dstPos)
{
	//LogAlwaysFmtPrint("cid=%d startmoveto ,m_beenSeelist.size()=%d ",m_pMaster->GetCid(),m_pMaster->GetBeSeenLst().size());
	SetTeamFollowFlag(false);
	Point3<float> startPos = m_pMaster->GetPos();
	float vSrcPos[3] = { startPos.x, startPos.y, startPos.z };
	float vDstPos[3] = { dstPos.x, dstPos.y, dstPos.z };
	VEC_FLAGS flgs;
	VEC_POINT3 path;
	CharIDType cid = m_pMaster->GetCid();

	if (!IsCanMove(startPos))
	{
		LogInfoFmtPrint("MovePart::MoveTo can not move cid=%lu,clientSpeed=%f,distance=%f", m_pMaster->GetCid(), m_pMaster->GetSpeed(),point3Length(startPos, m_pMaster->GetPos()));
		return false;
	}
		

	Map* map = g_GetMapMgr()->GetMap(m_pMaster->GetMapId());
	if (!map)
		return false;

	if (map->GetNavPath(vSrcPos, vDstPos, path, flgs))
	{
		//发现这个找路点的方法好像有问题，会找出来一个和起点一样的点，然后返回true,暂时在这里作个处理，后续再验证todo.
		if (path.size()<=1 && path[0] == vSrcPos )
		{
			return false;
		}

		if (m_curMovePath.Init(path, startPos))
			ReadyToMove();
		else
		{
			StopSelfMove();
			return false;
		}
			
	}
	else
		return false;

	ActorMove moveData;
	moveData.set_cid(cid);
	Vector3PB* pCurpos = new Vector3PB();
	pCurpos->set_x(startPos.x);
	pCurpos->set_y(startPos.y);
	pCurpos->set_z(startPos.z);
	moveData.set_allocated_currentpos(pCurpos);

	for (uint32_t i = 0; i < path.size(); i++)
	{
		Vector3PB* cpath = moveData.add_path();
		cpath->set_x(path[i].x);
		cpath->set_y(path[i].y);
		cpath->set_z(path[i].z);
		//if (i == path.size() - 1)
		//{
			//LogErrFmtPrint("startmoveto  ,cid=%d,startPos(%f,%f)", m_pMaster->GetCid(), path[i].x, path[i].z);
		//}
	}

	//客户端发来的玩家cid

	m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_MOVE, &moveData);		//广播给客户端这个玩家的移动信息

	m_enMovingFlag = enMovingFlag_Mouse;  //走鼠标移动
	m_pMaster->SetBeAttackFlag(true);
	//LogDebugFmtPrint("moveto client pos(%f,%f,%f)",m_pMaster->GetPos().x,m_pMaster->GetPos().y,m_pMaster->GetPos().z);
	//LogAlwaysFmtPrint("cid=%d end ,m_beenSeelist.size()=%d ", m_pMaster->GetCid(), m_pMaster->GetBeSeenLst().size());
	return true;
}


//处理摇杠移动
void MovePart::RockerMoveDoing(int32_t interval)
{
	if (m_pMaster->GetSceneId() <= 0) //客户端发送完移动消息，下线，或是离开场景后，可能会再进来一次，后面直接丢弃
	{
		StopSelfMove();
		return;
	}
	//m_StepStarttamp = g_GetGlobalServerTime()->Tick();
	//根据开始位置和方向，距离，算出目标点坐标
	float moveDistance = m_moveSpeed * interval / 1000.0f;

	//算出方向单位向量
	Point3<float> dir = m_pMaster->GetDir();
	//Point3<float> tmpDir = Point3<float>(dir.x / dir.length(), dir.y / dir.length(), dir.z / dir.length());

	Point3<float> desPos = m_pMaster->GetPos() + moveDistance*dir;

	//先算一下吧，后面再做客户端位置验证
	m_pMaster->SetPos(desPos);

	//LogAlwaysFmtPrint("player cid=%lld, pos(%f,%f,%f)", m_pMaster->GetCid(), desPos.x, desPos.y, desPos.z);
}

bool MovePart::TransToInScene(Point3<float>& dstPos)
{
	m_pMaster->SetPos(dstPos);
	ResetMoveInfo();
	ActorMove moveData;
	moveData.set_cid(m_pMaster->GetCid());
	Vector3PB *pCurPos = new Vector3PB;
	pCurPos->set_x(dstPos.x);
	pCurPos->set_y(dstPos.y);
	pCurPos->set_z(dstPos.z);
	moveData.set_allocated_currentpos(pCurPos);
	moveData.set_speed(m_pMaster->GetSpeed());

	//LogDebugFmtPrint("transtoInscene client pos(%f,%f,%f)", m_pMaster->GetPos().x, m_pMaster->GetPos().y, m_pMaster->GetPos().z);
	return m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_ACTOR_MOVE, &moveData);


}

//瞬间移动
bool MovePart::Teleporting(Point3<float> dstPos)
{
	if (m_pMaster->HasBuffStateNoMove())
	{
		return false;
	}

	m_pMaster->SetPos(dstPos);

	StopSelfMove();
	ActorMove moveData;
	moveData.set_cid(m_pMaster->GetCid());
	Vector3PB *pCurPos = new Vector3PB;
	pCurPos->set_x(dstPos.x);
	pCurPos->set_y(dstPos.y);
	pCurPos->set_z(dstPos.z);
	moveData.set_allocated_currentpos(pCurPos);
	return m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_TELEPORTING, &moveData,true);
}


//瞬移当前方向，指定距离的某个点上，里面会找一个可以放的点。
Point3<float>  MovePart::TeleportCurrentDis(float distance)
{
	//计算坐标
	Point3<float> targetPos;
	Point3<float> srcPos = m_pMaster->GetPos();
	targetPos = srcPos;
	Map* pMap = g_GetMapMgr()->GetMap(m_pMaster->GetMapId());
	bool ret = false;
	Point3<float> tmpdir=m_pMaster->GetDir();
	if (pMap)
	{
		for (float d = distance; d >= 0.1f; d -= 0.1f)
		{
			Point3<float> tmpPos = srcPos + tmpdir * d;
			targetPos = tmpPos;
			ret = pMap->FindNearestPos(tmpPos.x, tmpPos.z, tmpPos.y, &targetPos.x, &targetPos.z, &targetPos.y, nullptr);
			if (ret)
			{
				break;
			}
		}
	}

	Teleporting(targetPos);
	return targetPos;
}


bool MovePart::TransSceneInLogic(Scene *pdstScene, Point3<float> transPos, STransParam &transParam)
{

	//这里需要判断能否传送
	//TransSceneRsp rsp;
	//rsp.set_retcode(RET_SCENE_SCENCE_NOT_EXIT);
	//m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_TRANS_FAIL, &rsp);
	if (m_pMaster->CreatureKind()==CREATURE_PLAYER)
	{
		m_pMaster->SetCanBeSeenFlag(false);
	}
	

	//这里先通知客户端加载，再发送场景其它数据
	NotifyLoadMap notifyLoad;
	notifyLoad.set_mapid(pdstScene->GetMapId());
	Vector3PB *pTransPos = new Vector3PB;
	pTransPos->set_x(transPos.x);
	pTransPos->set_y(transPos.y);
	pTransPos->set_z(transPos.z);
	notifyLoad.set_allocated_transpos(pTransPos);

	//LogDebugFmtPrint("notify load map id:%d, sceneid:%u, cur_in_scene:%u ", pdstScene->GetMapId(), pdstScene->GetSceneId(), m_pMaster->GetSceneId());
	m_pMaster->SendDataToClient(LOGIC_TO_CLIENT_NOTIFY_LOAD_MAP, &notifyLoad);

	if (!m_pMaster->EnterScene(pdstScene->GetSceneId(), transPos, transParam))  //到这里是已经进场景了，如果进入失败，则说明玩家信息有误。
	{
		//通知前端切场景失败
		TransSceneRsp transRsp;
		transRsp.set_retcode(RET_SCENE_DST_NOT_EXIST);
		g_GetLogicService()->SendDataToClient(m_pMaster->GetCid(), EMODULE_ID_MOVE, LOGIC_TO_CLIENT_TRANS_FAIL, &transRsp);

		LogErrFmtPrint("[logic] MovePart::TransOtherScene failed....cid:%lu ,cursceneid:%u, dstsceneid:%u ,dstmapid:%u ", m_pMaster->GetCid(), m_pMaster->GetSceneId(), pdstScene->GetSceneId(), pdstScene->GetMapId());
		return false;
	}
	//ResetMoveInfo();


	StopMove();

	return  true;
}

bool MovePart::TransScene(uint32_t sceneId, Point3<float>& dstPos, uint32_t mapId, STransParam &transParam)
{
	bool result = false;
	bool retCode = false;
	{
		uint32_t curSceneId = m_pMaster->GetSceneId();
		if (m_pMaster->CreatureKind() != CREATURE_PLAYER && m_pMaster->CreatureKind() != CREATURE_MONSTER)
		{
			LogErrFmtPrint("only player can trans scene, this creature cannt, type:%d, cid:%lu", m_pMaster->CreatureKind(), m_pMaster->GetCid());
			return false;
		}

		//如果在位面中，先退出位面
		if (m_pMaster->GetPlaneID() > 0)
		{
			g_GetPlaneMgr()->LeavePlane(m_pMaster->GetCid());
		}
		
		//这里，如果在副本里用传送点，会从传送点配置中读一个地图ID，此时sceneid实际上是地图ID,这里加sceneId == m_pMaster->GetMapId() 只是为了在副本内可传送功能 add by wangxx
		//判断是否在同一个逻辑服里
		Scene* pScene = g_GetSceneMgr()->GetScene(sceneId);
		if (pScene)
		{
			//同一逻辑服则直接进入场景
			if (m_pMaster->GetScene() && (m_pMaster->GetSceneId()  == sceneId || m_pMaster->GetMapId() == sceneId))  //传送同一个场景，直接设置坐标
			{
				if (!Teleporting(dstPos))
				{
					LogErrFmtPrint("[logic] MovePart::TransOtherScene same scene failed  cid=%lu,sceneid=%d,despos(%f,%f,%f)", m_pMaster->GetCid(), sceneId, dstPos.x,dstPos.y,dstPos.z);
				}
			}
			else
			{

				//检查玩家是否能从当前场景切换到其他场景去
				ERetCode ret = RET_SUCCESS;
				if (!m_pMaster->CanTrans(ret, sceneId,mapId))
				{
					LogErrFmtPrint("[logic] MovePart::TransScene..... !m_pMaster->CanTrans()....sceneid:%u, mapid:%u, curscene:%u, cid:%lu,ret:%d ", sceneId, mapId, curSceneId, m_pMaster->GetCid(),ret);
					return false;
				}

				//传送不同场景，则需要走下面流程
				if (!TransSceneInLogic(pScene, dstPos, transParam))
				{
					LogErrFmtPrint("[logic] =====================MovePart::TransOtherScene failed....cid:%lu ,cursceneid:%u, dstsceneid:%u ,dstmapid:%u ",
						m_pMaster->GetCid(), m_pMaster->GetSceneId(), pScene->GetSceneId(), pScene->GetMapId());
				}
			}
		}
		else
		{

			//检查玩家是否能从当前场景切换到其他场景去
			ERetCode ret = RET_SUCCESS;
			if (!m_pMaster->CanTrans(ret, sceneId, mapId))
			{
				LogErrFmtPrint("[logic] MovePart::TransScene..... !m_pMaster->CanTrans()....sceneid:%u, mapid:%u, curscene:%u, cid:%lu,ret:%d ", sceneId, mapId, curSceneId, m_pMaster->GetCid(), ret);
				return false;
			}
			LogicCreatureTransSceneReq req;
			req.set_cursceneid(curSceneId);
			req.set_dstsceneid(sceneId);
			CreatureTransParam *protoParam = req.mutable_param();
			if (nullptr == protoParam)
			{
				LogErrFmtPrint("[logic] MovePart::TransScene..... nullptr == protoParam....sceneid:%u, mapid:%u, curscene:%u, cid:%lu,ret:%d ", sceneId, mapId, curSceneId, m_pMaster->GetCid(), ret);
				return false;
			}
			SceneTransTypeParam *protoTypeParam = protoParam->mutable_type_param();
			if (nullptr == protoTypeParam)
			{
				LogErrFmtPrint("[logic] MovePart::TransScene..... nullptr == protoParam....sceneid:%u, mapid:%u, curscene:%u, cid:%lu,ret:%d ", sceneId, mapId, curSceneId, m_pMaster->GetCid(), ret);
				return false;
			}
			protoParam->set_creature_cid(m_pMaster->GetCid());
			protoParam->set_creature_kind(m_pMaster->CreatureKind());
			protoTypeParam->set_src_map(transParam.srcMapId);
			protoTypeParam->set_trans_type(transParam.transType);
			protoTypeParam->set_dup_id(transParam.dupId);
			if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
			{
				Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
				if (nullptr != pPlayer)
				{
					for(int i = 0; i < PART_MAX; i++)
					{
						Part* pPart = pPlayer->GetPart(i);
						if (pPart)
						{
							pPart->BeforeChangeLogic();
						}
					}
					//切换逻辑节点之前先保存一次数据
					pPlayer->ChangeLogic();
					//
					PlayerTransParam *protoPlayer = protoParam->mutable_player_param();
					if (nullptr != protoPlayer)
					{
						uint32_t clientId = 0;
						uint32_t gateId = 0;
						pPlayer->GetGateClientId(gateId, clientId);
						protoPlayer->set_uid(pPlayer->GetUid());
						protoPlayer->set_channid(pPlayer->GetChannId());
						protoPlayer->set_client_id(clientId);
						protoPlayer->set_gateid(gateId);
						protoPlayer->set_uid(pPlayer->GetUid());
						protoPlayer->set_channid(pPlayer->GetChannId());
						PlayerSellBackItem *sellItems = protoPlayer->mutable_sell_items();
						if (nullptr != sellItems)
						{
							pPlayer->GetSellItems(*sellItems);
						}
						CharacterDBInfo *protoCharDB = protoPlayer->mutable_info();
						if (nullptr != protoCharDB)
						{
							pPlayer->GetSaveDBData(*protoCharDB);
							CharacterDBBaseInfo *protoCharDBBase = protoCharDB->mutable_basedata();
							if (nullptr != protoCharDBBase)
							{
								uint32_t curMapId = m_pMaster->GetMapId();
								if (g_GetMapCfgMgr()->IsUnionHomeMap(curMapId)
									|| g_GetMapCfgMgr()->IsUnionDunGeonMap(curMapId)
									) //如果是从工会场景或者工会地宫切到其他场景，需要把上一个场景设置为当前的工会场景
								{
									protoCharDBBase->set_lastmapid(curMapId);
									protoCharDBBase->set_lastsceneid(curSceneId);
									protoCharDBBase->set_lastposx(protoCharDBBase->enterposx());
									protoCharDBBase->set_lastposy(protoCharDBBase->enterposy());
									protoCharDBBase->set_lastposz(protoCharDBBase->enterposz());
								}
								else if (!g_GetMapCfgMgr()->IsDynamic(curMapId)) //当前地图不是动态地图,把上一个场景参数设置为当前场景参数
								{
									protoCharDBBase->set_lastmapid(curMapId);
									protoCharDBBase->set_lastsceneid(curSceneId);
									protoCharDBBase->set_lastposx(protoCharDBBase->enterposx());
									protoCharDBBase->set_lastposy(protoCharDBBase->enterposy());
									protoCharDBBase->set_lastposz(protoCharDBBase->enterposz());
								}
								//设置目标场景和目标地图以及坐标
								protoCharDBBase->set_enter_scene_id(sceneId);
								protoCharDBBase->set_enter_map_id(mapId);
								protoCharDBBase->set_enterposx(dstPos.x);
								protoCharDBBase->set_enterposy(dstPos.y);
								protoCharDBBase->set_enterposz(dstPos.z);								
							}

						}
					}

				} // end of if (nullptr != pPlayer)
			}
			else if (m_pMaster->CreatureKind() == CREATURE_MONSTER)
			{
				Monster *pMonster = dynamic_cast<Monster*>(m_pMaster);
				if (nullptr != pMonster)
				{
					for(int i = 0; i < PART_MAX; i++)
					{
						Part* pPart = pMonster->GetPart(i);
						if (pPart)
						{
							pPart->BeforeChangeLogic();
						}
					}
					MonsterTransParam *protoMonster = protoParam->mutable_mons_param();
					if (nullptr != protoMonster)
					{
						protoMonster->set_monster_id(pMonster->GetConfigId());
						protoMonster->set_monster_cid(pMonster->GetCid());
						protoMonster->set_hp(pMonster->GetAttr(C_HP));
						protoMonster->set_mspeed(pMonster->GetSpeed());
						protoMonster->set_scene_id(sceneId);
						if (PARENT_MONSTER_TYPE_MOVE_BIAOCHE == pMonster->GetParentMonsterType() || PARENT_MONSTER_TYPE_MOVE_TEAM_BIAOCHE == pMonster->GetParentMonsterType())
						{
							MonsterTransParam::EscortParam *escortParam = protoMonster->mutable_escort();
							if (nullptr != escortParam)
							{
								escortParam->set_master_cid(pMonster->GetMonsterMasterCID());
								escortParam->set_master_name(pMonster->GetMasterName());
								escortParam->set_union_id(pMonster->GetMonsterUnionID());
								escortParam->set_camp_id(pMonster->GetMonsterCampID());
								escortParam->set_escort_level(pMonster->GetAttr(C_LEVEL));
							}
						}
					}
				}
			} // end of if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
			retCode = g_GetLogicService()->SendDataToCenter(EMODULE_ID_SCENE, LOGIC_CREATURE_TRANS_SCENE_REQ_CENTER, &req);
			MMOLOG_PROCESS_ERROR(retCode);
		}

		ResetMoveInfo();
	}

	m_pMaster->SetBeAttackFlag(false);

	result = true;
Exit0:
	return result;

}

void MovePart::ReadyToMove()
{
	//开始移动之前，先把自身移动状态清除
	StopSelfMove();

	float totalPathLength = m_curMovePath.GetTotalPathLength(); //路径长度
	//定时器触发次数=总长度时/间间隔距离(取余的结果只要大于0，也要触发一次定时器来移动)
	float floatSpeed = (totalPathLength / m_moveSpeed) * 1000.0f / (float)m_moveIntervalTime;
	uint32_t intStepCount = (uint32_t)floatSpeed;
	if (intStepCount == 0)
	{
		m_curleftStep = 1;
	}
	else
	{
		m_curleftStep = fmod(floatSpeed, intStepCount) > 0.0f ? intStepCount + 1 : intStepCount;
	}
	
	if (m_curleftStep <= 0)
		return;
	//m_curleftStep += 40;
	//LogDebugFmtPrint("move count :%d", m_curleftStep);

	//m_curleftStep = fmod(totalPathLength, m_curSpeed * 1000.0f / (float)INTERVAL_MOVE_TIME) > 0.0f ?  outputSpeed: outputSpeed+ 1;
	m_StepStarttamp = g_GetGlobalServerTime()->Tick();

	KillTimedo(TIMEID_MOVING);
	if (SetTimedo(TIMEID_MOVING, m_moveIntervalTime, m_curleftStep))
	{

		m_enMovingFlag = enMovingFlag_Mouse;

		//开始移动事件触发
		StartMove startm;
		startm.fspeed = m_moveSpeed;
		g_GetEvent()->FireExecute(EVENT_START_MOVE, m_pMaster->GetCid(), m_pMaster->CreatureKind(), &startm, sizeof(StartMove));

	}
}

void MovePart::SkillReadyToMove(float skillSpeed)
{
	//开始移动之前，先把自身移动状态清除
	StopSelfMove();

	//m_lastSpeed = m_pMaster->GetSpeed();
	m_pMaster->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(m_pMaster->CreatureKind(),C_MSPEED), (skillSpeed - m_pMaster->GetSpeed()) * 1000, true);
	float totalPathLength = m_curMovePath.GetTotalPathLength(); //路径长度
	//定时器触发次数=总长度时/间间隔距离(取余的结果只要大于0，也要触发一次定时器来移动)
	float floatSpeed = (totalPathLength / m_pMaster->GetSpeed()) * 1000.0f / (float)m_moveIntervalTime;
	uint32_t intStepCount = (uint32_t)floatSpeed;
	m_curleftStep = fmod(floatSpeed, intStepCount) > 0.0f ? intStepCount + 1 : intStepCount;
	if (m_curleftStep <= 0)
		return;

	//m_curleftStep = fmod(totalPathLength, m_curSpeed * 1000.0f / (float)INTERVAL_MOVE_TIME) > 0.0f ?  outputSpeed: outputSpeed+ 1;
	m_StepStarttamp = g_GetGlobalServerTime()->Tick();

	KillTimedo(TIMEID_MOVING);
	if (SetTimedo(TIMEID_MOVING, m_moveIntervalTime, m_curleftStep))
	{
		m_enMovingFlag = enMovingFlag_Mouse;
		
		//开始移动事件触发
		StartMove startm;
		startm.fspeed = m_pMaster->GetSpeed();
		g_GetEvent()->FireExecute(EVENT_START_MOVE, m_pMaster->GetCid(), m_pMaster->CreatureKind(), &startm, sizeof(StartMove));
	}
}

void MovePart::StopMove()
{
	ResetMoveInfo();
	ActorMove moveData;
	Point3<float> curpos = m_pMaster->GetPos();
	Vector3PB *pCurPos = new Vector3PB;
	pCurPos->set_x(curpos.x);
	pCurPos->set_y(curpos.y);
	pCurPos->set_z(curpos.z);
	moveData.set_cid(m_pMaster->GetCid());
	moveData.set_allocated_currentpos(pCurPos);
	moveData.set_speed(m_pMaster->GetSpeed());
	m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_MOVE, &moveData);		//广播给客户端这个玩家的停止移动的信息（路径为空）

	//if (m_pMaster->CreatureKind() == CREATURE_PLAYER)
	//{
	//	m_pMaster->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(C_MSPEED), 0, false);
	//}
		
	//LogDebugFmtPrint("StopMove client pos(%f,%f,%f)", m_pMaster->GetPos().x, m_pMaster->GetPos().y, m_pMaster->GetPos().z);
}

//获取移动信息
void MovePart::GetMoveingState(ActorMove &actorMove, ActorRockerMove & rockmove)
{
	//LogDebugFmtPrint("move state flag = %d  cid=%llu", m_enMovingFlag,m_pMaster->GetCid());
	if (m_enMovingFlag == enMovingFlag_None)
	{
		//没移动，不用同步
		return;
	}
	else if (m_enMovingFlag == enMovingFlag_Mouse)
	{
		//先算出当前位置
		Vector3PB* pCurpos = new Vector3PB();
		//鼠标移动，同上目标点和现在位置
		//actorMove.set_cid(m_pMaster->GetCid());
		pCurpos->set_x(m_pMaster->GetPos().x);
		pCurpos->set_y(m_pMaster->GetPos().y);
		pCurpos->set_z(m_pMaster->GetPos().z);
		actorMove.set_speed(m_pMaster->GetSpeed());
		actorMove.set_allocated_currentpos(pCurpos);

		VEC_POINT3 tmpPath;
		m_curMovePath.GetLeftPath(tmpPath);

		for (uint32_t i = 0; i < tmpPath.size(); i++)
		{
			Vector3PB* cpath = actorMove.add_path();
			cpath->set_x(tmpPath[i].x);
			cpath->set_y(tmpPath[i].y);
			cpath->set_z(tmpPath[i].z);
		}

	}
	else if (m_enMovingFlag == enMovingFlag_Rock)
	{
		//同步摇杆移动
		//rockmove.set_cid(m_pMaster->GetCid());
		Vector3PB* pCurpos = new Vector3PB();
		pCurpos->set_x(m_pMaster->GetPos().x);
		pCurpos->set_y(m_pMaster->GetPos().y);
		pCurpos->set_z(m_pMaster->GetPos().z);
		rockmove.set_allocated_currentpos(pCurpos);
		rockmove.set_currentrange(m_fRockAngle);
		rockmove.set_movetype(m_fRockType);
		rockmove.set_speed(m_pMaster->GetSpeed());
	}
}


void MovePart::StopSelfMove()
{
	if (m_enMovingFlag == enMovingFlag_None)
		return;

	m_curleftStep = 0;
	KillTimedo(TIMEID_MOVING);
	//先停掉遥感走
	KillTimedo(TIMEID_ROCKER_MOVING);
	m_enMovingFlag = enMovingFlag_None;
	m_StepStarttamp = 0;
	m_lastMoveTime = 0;
	//if (m_pMaster->CreatureKind()==CREATURE_PLAYER)
	//{
	//	m_pMaster->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(C_MSPEED), 0, false);
	//}
}

void MovePart::ResetMoveInfo()
{

	if (m_enMovingFlag == enMovingFlag_None)
		return;

	if (m_enMovingFlag == enMovingFlag_Mouse)
	{
		int32_t moveTime = g_GetGlobalServerTime()->Tick() - m_StepStarttamp;
		if (moveTime > 0)
			SyncPosition(moveTime);//设置开始走一步到强制停止的位移
	}

	m_fRockAngle = 0;
	m_fRockType = ActorRockerMove_Type_Up;
	StopSelfMove();
}

void MovePart::OnTimer(uint32_t nTimerId)
{
	switch (nTimerId)
	{
	case TIMEID_MOVING:
		SyncPosition(g_GetGlobalServerTime()->Tick() - m_StepStarttamp);//设置开始走一步到强制停止的位移
		break;
	case TIMEID_ROCKER_MOVING:
		RockerMoveDoing(g_GetGlobalServerTime()->Tick() - m_StepStarttamp);
		break;
	case TIMEID_CHEAT_MOVE:
		IsJudgeCheatMove();
		break;
	default:
		break;
	}
}

//判断是否作弊
bool MovePart::IsJudgeCheatMove()
{
	if (m_moveErrorNum > 2)
	{
		Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
		if (pPlayer)
		{
			pPlayer->SendKickPlayerToCenter();

			LogErrFmtPrint("player cheat num=%d,kick player  ",m_moveErrorNum);
		}
	}
	else
	{
		m_moveErrorNum = 0;
	}

	return true;
}

//走一步
void MovePart::SyncPosition(int32_t interval /* = INTERVAL_MOVE_TIME */)
{
	
	if (m_pMaster->GetSceneId() <= 0 || interval <= 0 || !m_pMaster->GetCanBeSeenFlag())  //客户端发送完移动消息，下线，或是离开场景后，可能会再进来一次，后面直接丢弃
	{	
		StopSelfMove();
		return;
	}
	
	float moveDistance = m_moveSpeed * interval / 1000.0f;

	Point3<float> point(m_pMaster->GetPos());
	bool moveDone = m_curMovePath.MapPathDistanceToPoint(moveDistance, point);

	m_curleftStep--;
	m_StepStarttamp = g_GetGlobalServerTime()->Tick();

	if (moveDone)
	{
		m_pMaster->SetPos(point);
		//客户端发来的玩家当前位置
		if (m_pMaster->CreatureKind() == CREATURE_MONSTER || m_pMaster->CreatureKind() == CREATURE_NPC)
		{
			StopMove();
			g_GetEvent()->FireExecute(EVENT_END_MOVE, m_pMaster->GetCid(), m_pMaster->CreatureKind(), nullptr, 0);
		}
		else
		{
			StopSelfMove();
		}
	}
	else
	{
		Point3<float> pos = point - m_pMaster->GetPos();
		m_pMaster->SetDir(pos);
		m_pMaster->SetPos(point);
	}

}

void MovePart::C2Move(const char* data, uint32_t len)
{

	SetTeamFollowFlag(false);

	ActorMove moveData;
	
	if (!moveData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}

	if (moveData.has_sceneid())
	{
		if (moveData.sceneid()!=m_pMaster->GetMapId()) //消息那里暂时没改，实际上客记端全部用的是mapid,所以这里用mapid在判断
		{
			LogDebugFmtPrint("no same scene can not move");
			return;
		}
	}

	if (moveData.cid() != m_pMaster->GetCid())
	{
		return;
	}
	
	if (m_enMovingFlag != enMovingFlag_Mouse)
	{
		ResetMoveInfo();
	}

	//if (m_pMaster->CreatureKind()!=CREATURE_PET &&  moveData.has_speed() && !IsCanMoveSpeed(moveData.speed()))
	//{
	//	return;
	//}

	//其它地方有用到这部分，抽出来单独做成一个方法
	C2MoveFun(moveData,true);


	/*if (C2MoveFun(moveData))
	{
		moveData.set_speed(m_pMaster->GetSpeed());
		m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_MOVE, &moveData);		//广播给客户端这个玩家的移动信息
	}*/

	//LogDebugFmtPrint("C2Move client pos(%f,%f,%f)", m_pMaster->GetPos().x, m_pMaster->GetPos().y, m_pMaster->GetPos().z);
}

 //组队移动
void MovePart::C2TeamMove(const char* data, uint32_t len)
{
	if (m_enMovingFlag != enMovingFlag_None)
	{
		ResetMoveInfo();
	}


	TeamMove moveData;

	if (!moveData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}
	Scene *pScene = m_pMaster->GetScene();
	if (nullptr == pScene)
	{
		LogErrFmtPrint("[logic] MovePart::C2TeamMove...nullptr == pScene....cid%lu ",m_pMaster->GetCid());
		return;
	}
	
	for (int i = 0; i < (int)moveData.movedate_size();++i)
	{
		if (moveData.movedate(i).cid() == m_pMaster->GetCid() )
		{
			if (!C2MoveFun(moveData.movedate(i)))
			{
				return;
			}
			continue;
		}
		//Player * pPlayer = g_GetCreatureMgr()->GetPlayer(moveData.movedate(i).cid());
		Player * pPlayer = pScene->GetPlayer(moveData.movedate(i).cid());
		if (pPlayer)
		{
			MovePart* pPart = dynamic_cast<MovePart*>(pPlayer->GetPart(PART_MOVE));
			if (pPart)
			{
				pPart->SetTeamFollowFlag(true,m_pMaster->GetSpeed());

				if (!pPart->C2MoveFun(moveData.movedate(i),false,true))
				{
					return;
				}
			}
		}
		else
		{

		}		
	}
	m_pMaster->BroadCastData(LOGIC_TO_CLIENT_TEAM_MOVE, &moveData);		//广播给客户端这个玩家的移动信息
}



//玩家摇杠移动
void MovePart::C2RockerMove(const char* data, uint32_t len)
{

	SetTeamFollowFlag(false);

	ActorRockerMove moveData;
	if (!moveData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}

	C2RockerMoveFun(moveData, true);
}

//组队摇杆移动
void MovePart::C2TeamRockMove(const char* data, uint32_t len)
{
	TeamRockerMove moveData;
	if (!moveData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}

	for (int i = 0; i < (int)moveData.movedate_size(); ++i)
	{
		if (m_pMaster->GetCid() == moveData.movedate(i).cid())
		{
			if (!C2RockerMoveFun(moveData.movedate(i)))
			{
				return;
			}
			continue;
		}

		//Player * pPlayer = g_GetPlayerMgr()->GetPlayer(moveData.movedate(i).cid());
		//if (pPlayer)
		//{
		//	MovePart* pPart = dynamic_cast<MovePart*>(pPlayer->GetPart(PART_MOVE));
		//	if (pPart)
		//	{
		//		pPart->C2MoveFun(moveData.movedate(i));
		//	}
		//}
		//else
		//{
		//	CPet * pPet = g_GetPetMgr()->GetPet(moveData.movedate(i).cid());
		//	if (pPet)
		//	{
		//		MovePart * pPart = dynamic_cast<MovePart*>(pPet->GetPart(PART_MOVE));
		//		if (pPart)
		//		{
		//			pPart->C2MoveFun();
		//		}
		//	}
		//}

	}

	m_pMaster->BroadCastData(LOGIC_TO_CLIENT_TEAM_ROCKER_MOVE, &moveData);		//广播给客户端这个玩家的移动信息
}

//组队传送消息
void MovePart::C2TeamTranScene(const char* data, uint32_t len)
{
	TeamTransSceneReq teamTransInfo;
	if (!teamTransInfo.ParseFromArray(data, len))
		return;
	if (!m_pMaster->GetAttr(C_TEAM_LEADER_ID) || m_pMaster->GetAttr(C_TEAM_ID) <= 0)
	{
		LogErrFmtPrint("C2TeamTranScene...player not team leader or not join team...cid:%lu, teamid:%u ", m_pMaster->GetCid(), m_pMaster->GetAttr(C_TEAM_ID));
	}
	ERetCode ret = RET_SUCCESS;
	CharIDType cid = m_pMaster->GetCid();
	uint32_t nTeamID = m_pMaster->GetAttr(C_TEAM_ID);
	TransSceneReq transInfo = teamTransInfo.transinfo();
	//先根据传送点获取目标地图和场景
	Point3<float> dstPos;
	dstPos.x = transInfo.dstpos().x();
	dstPos.y = transInfo.dstpos().y();
	dstPos.z = transInfo.dstpos().z();
	TransSceneTmpInfo transTmp;
	if (!GetDstInfoFromC(transInfo.typeid_(), transInfo.instanceid(), dstPos, transTmp))
	{
		return;
	}
	//队长不能传送
	if (!m_pMaster->CanTrans(ret, transTmp.dstSceneId, transTmp.dstmapId))
	{
		LogErrFmtPrint("C2TeamTranScene...m_pMaster->CanTrans failed..cid:%lu ,dstscene:%u, dstmap:%u ,ret:%d ", cid, transTmp.dstSceneId, transTmp.dstmapId, (int32_t)ret);
		return;
	}	
	MAP_Player mapMemPlayer;
	mapMemPlayer.clear();
	SET_UINT64 setNotTrans;//不能传送的队员
	setNotTrans.clear();	
	//校验其他人是否再同一队伍
	for (int32_t j = 0; j < (int32_t)teamTransInfo.cid_size(); ++j)
	{
		CharIDType memCid = teamTransInfo.cid(j);
		if (memCid == cid)
		{
			continue;
		}
		Player * pMemPlayer = g_GetCreatureMgr()->GetPlayer(memCid);
		if (nullptr == pMemPlayer)
		{
			LogErrFmtPrint("C2TeamTranScene...nullptr == pMemPlayer...memCid:%lu, cid:%lu,teamid:%u ", memCid, cid, nTeamID);
			continue;
		}
		if (pMemPlayer->GetAttr(C_TEAM_ID) != nTeamID)
		{
			LogErrFmtPrint("C2TeamTranScene...pMemPlayer->GetAttr(C_TEAM_ID) != nTeamID...memCid:%lu,memTeamID:%u, cid:%lu,teamid:%u ", memCid, pMemPlayer->GetAttr(C_TEAM_ID), cid, nTeamID);
			return;
		}
		if (!pMemPlayer->CanTrans(ret, transTmp.dstSceneId, transTmp.dstmapId))
		{
			setNotTrans.insert(memCid);
			LogErrFmtPrint("C2TeamTranScene...pMemPlayer->CanTrans failed..memcid:%lu ,dstscene:%u, dstmap:%u ,ret:%d ", memCid, transTmp.dstSceneId, transTmp.dstmapId, (int32_t)ret);
			continue;
		}
		mapMemPlayer[memCid] = pMemPlayer;
	}
	
	//自己
	StopSelfMove();
	LogDebugFmtPrint("[logic] MovePart::C2TeamTranScene....cid:%lu  dstscene:%u, dstmapid:%u, dstpos:[%f,%f,%f] ", cid, transTmp.dstSceneId, transTmp.dstmapId, transTmp.dstPos.x, transTmp.dstPos.y, transTmp.dstPos.z);
	STransParam transParam;
	transParam.srcMapId = m_pMaster->GetMapId();
	transParam.transType = ETransType_TeamFollow;
	TransScene(transTmp.dstSceneId, transTmp.dstPos, transTmp.dstmapId, transParam);

	//队员
	MAP_Player::iterator iterMem = mapMemPlayer.begin();
	for (; iterMem != mapMemPlayer.end(); ++iterMem)
	{
		CharIDType memCid = iterMem->first;
		Player * pMemPlayer = iterMem->second;
		if (nullptr != pMemPlayer)
		{
			MovePart * pMemMovePart = dynamic_cast<MovePart*>(pMemPlayer->GetPart(PART_MOVE));
			if (nullptr != pMemMovePart)
			{
				pMemMovePart->StopSelfMove();
				LogDebugFmtPrint("[logic] MovePart::C2TeamTranScene....other cid:%lu  dstscene:%u, dstmapid:%u, dstpos:[%f,%f,%f] ", memCid, transTmp.dstSceneId, transTmp.dstmapId, transTmp.dstPos.x, transTmp.dstPos.y, transTmp.dstPos.z);
				STransParam transParamEx;
				transParamEx.transType = ETransType_TeamFollow;
				transParamEx.srcMapId = pMemPlayer->GetMapId();
				pMemMovePart->TransScene(transTmp.dstSceneId, transTmp.dstPos, transTmp.dstmapId, transParamEx);
			}
		}
	}
	//不能传送的队员需要取消跟随
	g_GetGTeamMgr()->CancelFllow(nTeamID, setNotTrans);
}

bool MovePart::C2MoveFun(const ActorMove & moveData, bool bBroad /*= false*/, bool teamMove)
{
	if (moveData.has_sceneid())
	{
		if (moveData.sceneid() != m_pMaster->GetMapId())
		{
			LogDebugFmtPrint("no same scene can not move");
			return false;
		}
	}

	//客户端发来的玩家当前位置
	Point3<float> curPos(moveData.currentpos().x(), moveData.currentpos().y(), moveData.currentpos().z());


	//校验位置信息
	if (!IsCanMove(curPos, moveData.speed()))
	{
		//LogInfoFmtPrint("MovePart::C2MoveFun can not move cid=%lu,speed =%f,clientSpeed=%f,distance=%f", m_pMaster->GetCid(), m_pMaster->GetSpeed(), moveData.speed(), point3Length(curPos, m_pMaster->GetPos()));
		return false;
	}

	//if (!teamMove)
	//{
	//	JudgeMove(curPos, moveData.speed());
	//}
	
	//路径初始化成功则开始移动
	if (m_curMovePath.Init(moveData))
	{
		ReadyToMove();
		m_enMovingFlag = enMovingFlag_Mouse;
	}
	else
	{
		StopSelfMove();
	}

	//if (m_enMovingFlag != enMovingFlag_None)
	{
		if (bBroad)
		{
			//广播路径给旧视野里面的人，需要在SetPos之前广播
			ActorMove &newmoveData = const_cast<ActorMove&>(moveData);
			newmoveData.set_speed(m_pMaster->GetSpeed());
			m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_MOVE, &newmoveData);
		}

		m_pMaster->SetPos(curPos);
		//if (moveData.has_speed())
		//{
		//	m_pMaster->SetAttr(g_GetAttrMgr()->GetSKillCNumAttr(C_MSPEED), (moveData.speed() - m_pMaster->GetSpeed()) * 1000, false);
		//	//LogDebugFmtPrint("teammove speed =%d,current=%d", moveData.speed(),m_pMaster->GetPAttrValue(P_MSPEED));
		//}
	}
	
	m_pMaster->SetBeAttackFlag(true);

	return true;
}

bool MovePart::C2RockerMoveFun(const ActorRockerMove & moveData,bool isBroad/* = false*/)
{
	//LogDebugFmtPrint("receive MovePart::C2RockerMoveFun tick=%llu",Time::Tick());
	//如果自己还在鼠标移动中，先停止
	
	if (m_enMovingFlag == enMovingFlag_None && moveData.movetype() != ActorRockerMove_Type_Stop)
	{
		//开始移动事件触发
		StartMove startm;
		startm.fspeed = m_pMaster->GetSpeed();
		g_GetEvent()->FireExecute(EVENT_START_MOVE, m_pMaster->GetCid(), m_pMaster->CreatureKind(), &startm, sizeof(StartMove));
	}

	if (m_enMovingFlag == enMovingFlag_Mouse)
	{
		ResetMoveInfo();
	}


	if (moveData.has_sceneid())
	{
		if (moveData.sceneid() != m_pMaster->GetMapId())   //消息那里暂时没改，实际上客记端全部用的是mapid,所以这里用mapid在判断
		{
			LogDebugFmtPrint("no same scene can not move");
			return false;
		}
	}

	//客户端发来的玩家当前位置
	Point3<float> curPos(moveData.currentpos().x(), moveData.currentpos().y(), moveData.currentpos().z());

	Point3<float> oldPos = m_pMaster->GetPos();
	//设置当前朝向
	float x = sin(moveData.currentrange());
	float z = cos(moveData.currentrange());
	Point3<float> dir(x, 0, z);

	float tmpX = abs(curPos.x - oldPos.x);
	float tmpZ = abs(curPos.z - oldPos.z);
	float len = tmpX*tmpX + tmpZ*tmpZ;
	Point3<float> targetPos = curPos;

	uint64_t curTime = Time::Now().UnixMSec();

	//如果是停止和有障碍，不判断时间间隔
	if (moveData.movetype() == ActorRockerMove_Type_Stop || moveData.movetype() == ActorRockerMove_Type_Block)
	{
		m_lastMoveTime = 0;
	}

	//如果是翻滚，服务器时时更新下位置
	if (moveData.movetype() == ActorRockerMove_Type_DownRoll || moveData.movetype() == ActorRockerMove_Type_UpRoll)
	{
		float distance = point2Length(curPos, oldPos);
		//翻滚CD判断
		if (m_lastRockRollTime >0 && (distance> g_constRockMoveDistance || distance - (curTime - m_lastRockRollTime)*g_constRockSpeed >0.2))
		{
			Teleporting(m_pMaster->GetPos());
			LogErrFmtPrint("rockroll cd time error");
			return false;
		}
		//翻滚最大距离判断 最大只能是12米		
		if (len < 0 || len > (float)(g_constRockMoveDistance * g_constRockMoveDistance))
		{
			MMOLOG_FMT_ERROR("[logic] MovePart::C2RockerMoveFun client req roll pos error...Cid:%lu, len:%f", m_pMaster->GetCid(), len);
			return false;
		}

		m_lastRockRollTime = curTime;
	}
	else
	{
		float intervalTime = 0;
		if (m_lastMoveTime > 0)
		{
			intervalTime = (curTime - m_lastMoveTime) / 1000.0f;
		}


		//LogDebugFmtPrint("rockmove curpos(%f,%f),destPos(%f,%f),distance=%f",m_pMaster->GetPos().x,m_pMaster->GetPos().z,curPos.x,curPos.z,point2Length(m_pMaster->GetPos(),curPos));

		//校验位置信息
		if (!IsCanMove(curPos, moveData.speed(), intervalTime))
		{
			LogInfoFmtPrint("MovePart::C2RockerMoveFun can not move cid=%lu,speed =%f,clientSpeed=%f,distance=%f", m_pMaster->GetCid(), m_pMaster->GetSpeed(), moveData.speed(), point3Length(curPos, m_pMaster->GetPos()));
			return false;
		}
		
		//JudgeMove(curPos, moveData.speed(), intervalTime);


		m_lastMoveTime = curTime;
	}

	if (isBroad)
	{
		//广播给客户端这个玩家的移动信息,这里主要是广播旧视野里面的人，新加入视野的人在SetPos里面会通知
		ActorRockerMove &newmoveData = const_cast<ActorRockerMove&>(moveData);
		newmoveData.set_speed(m_pMaster->GetSpeed());
		m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_ROCKER_MOVE, &newmoveData);
	}

	m_fRockAngle = moveData.currentrange();
	m_fRockType = moveData.movetype();

	if (m_fRockType == ActorRockerMove_Type_Stop)
	{
		m_enMovingFlag = enMovingFlag_None;
	}
	else
	{
		m_enMovingFlag = enMovingFlag_Rock;
	}
	
	m_pMaster->SetPos(targetPos);
	m_pMaster->SetDir(dir);


	//如果是移动，则设置定时器
	KillTimedo(TIMEID_ROCKER_MOVING);

	m_pMaster->SetBeAttackFlag(true);
	return true;
}


uint64_t testlastTime = 0;
//玩家同步位置
void MovePart::C2UpdatePos(const char* data, uint32_t len)
{
	
	ActorPosUpDate updatePos;
	if (!updatePos.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}

	if (updatePos.cid()!=m_pMaster->GetCid())
	{
		LogDebugFmtPrint("MovePart::C2UpdatePos cid=%lu,m_cid=%lu", updatePos.cid(), m_pMaster->GetCid());
		return;
	}
	else
	{
		//客户端发来的玩家当前位置
		Point3<float> curPos(updatePos.currentpos().x(), updatePos.currentpos().y(), updatePos.currentpos().z());

		//当前方向
		Point3<float> curDir(updatePos.currentdir().x(), updatePos.currentdir().y(), updatePos.currentdir().z());

		
		float interverTime = 0;
		if (m_lastMoveTime > 0)
		{
			interverTime = (Time::Now().UnixMSec() - m_lastMoveTime) / 1000.0f;
		}

		if (!IsCanMove(curPos, updatePos.speed(), interverTime))
		{
			//LogInfoFmtPrint("MovePart::C2UpdatePos can not move cid=%lu,speed =%f,clientpos(%f,%f,%f),curpos(%f,%f,%f), distance=%f", m_pMaster->GetCid(), m_pMaster->GetSpeed(),
			//	curPos.x, curPos.y, curPos.z, m_pMaster->GetPos().x, m_pMaster->GetPos().y, m_pMaster->GetPos().z, point3Length(curPos, m_pMaster->GetPos()));
			return;
		}
		
		//JudgeMove(curPos, updatePos.speed(), interverTime);
		

		if ((updatePos.has_sceneid()) && (m_pMaster->GetMapId() != updatePos.sceneid()))
		{
			LogDebugFmtPrint("update sceneid error current=%d,sendsceneid=%d", m_pMaster->GetMapId(), updatePos.sceneid());
			return;
		}


		
		//m_StepStarttamp = g_GetGlobalServerTime()->Tick();
		//StopSelfMove();
		if (enMovingFlag_Mouse==m_enMovingFlag)  //鼠标导航是过200ms发一次位置同步消息
		{
			m_lastMoveTime = Time::Now().UnixMSec();
		}
		else
		{
			m_pMaster->SetPos(curPos);
			m_pMaster->SetDir(curDir);

			if (!updatePos.isend())
			{
				m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_POS_UPDATE, &updatePos);		//广播给客户端这个玩家的移动信息
			}
		}
	}


}

//更新组队玩家位置
void MovePart::C2UpdateTeamPos(const char* data, uint32_t len)
{
	TeamPosUpDate teamData;

	if (!teamData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] C2UpdateTeamPos parse failed...");
		return;
	}

	//更新每一个位置
	for (int i = 0; i < (int)teamData.updateinfo_size();++i)
	{
		ActorPosUpDate dateinfo = teamData.updateinfo(i);
		Player *pPlayer = g_GetCreatureMgr()->GetPlayer(dateinfo.cid());
		if (pPlayer)
		{
			//客户端发来的玩家当前位置
			Point3<float> curPos(dateinfo.currentpos().x(), dateinfo.currentpos().y(), dateinfo.currentpos().z());
			//当前方向
			Point3<float> curDir(dateinfo.currentdir().x(), dateinfo.currentdir().y(), dateinfo.currentdir().z());
			
			if (!IsCanMove(curPos))
			{
				return;
			}

			pPlayer->SetPos(curPos);
			pPlayer->SetDir(curDir);
			if (dateinfo.cid()==m_pMaster->GetCid())
			{
				StopSelfMove();
				continue;
			}
			MovePart *pPart = dynamic_cast<MovePart*>(pPlayer->GetPart(PART_MOVE));
			if (pPart)
			{
				pPart->StopSelfMove();
			}
		}
	}

	if (!teamData.updateinfo(0).isend())
	{
		m_pMaster->BroadCastData(LOGIC_TO_CLIENT_TEAM_POS_UPDATE, &teamData);		//广播给客户端这个玩家的移动信息
	}
}


void MovePart::C2TransFinish(const char* data, uint32_t len)
{
	Player * pPlayer = dynamic_cast<Player*>(m_pMaster);
	if (pPlayer)
	{
		pPlayer->SetCanBeSeenFlag(true);
		pPlayer->UpdateNineGridLst();
	}
}


void MovePart::C2SkillMove(const char* data, uint32_t len)
{
	if (m_enMovingFlag!=enMovingFlag_None)
	{
		ResetMoveInfo();
	}
	ActorSkillMove moveData;
	
	if (!moveData.ParseFromArray(data, len))
	{
		MMOLOG_FMT_ERROR("[logic] ActorMove parse failed...");
		return;
	}

	if (moveData.cid() != m_pMaster->GetCid())
	{
		return;
	}

	//客户端发来的玩家当前位置
	Point3<float> curPos(moveData.currentpos().x(), moveData.currentpos().y(), moveData.currentpos().z());

	//if (!IsCanMove(curPos))
	//{
	//	LogInfoFmtPrint("MovePart::C2SkillMove can not move cid=%lu,speed =%f,distance=%f", m_pMaster->GetCid(), m_pMaster->GetSpeed(), point3Length(curPos, m_pMaster->GetPos()));
	//	return;
	//}
		

	//路径初始化成功则开始移动
	if (m_curMovePath.Init(moveData))								
		SkillReadyToMove(moveData.speed());
	else
		m_enMovingFlag = enMovingFlag_None;

	m_pMaster->SetPos(curPos);
}

bool MovePart::IsCanMove(Point3<float> &msgCurPos, float fSpeed, float interverTimeSec)
{

	//检查是否有禁止移动的buff
	if (m_pMaster->HasBuffStateNoMove() )
	{
		LogInfoFmtPrint("MovePart::IsCanMove  cid=%lu,hasbuffnomove", m_pMaster->GetCid());
		return false;
	}

	//正在传送，不接收移动消息，主要是为了处理传送过种中，客户端还会发移动消息，此时，客户端在加载，会跑到不合法点上
	if (!m_pMaster->GetCanBeSeenFlag())
	{
		LogInfoFmtPrint("MovePart::IsCanMove  cid=%lu,is not beseen", m_pMaster->GetCid());
		return false;
	}
	return true;
}

bool MovePart::JudgeMove(Point3<float> &msgCurPos, float fSpeed, float interverTimeSec)  //判断移动合法性
{
	//检查当前位置是否合理
	//Point3<float> curPos = m_pMaster->GetPos();
	//float distance = point2Length(curPos, msgCurPos);
	//if (interverTimeSec <= 0) //为0表示不判断时间间隔
	//{
	//	interverTimeSec = g_constMoveMaxTime;
	//}

	////这里先这样子判断
	////先判断两条消息时间不能小于165ms，这个是防止用外挂改客户端时间,这里作个1帧(33ms)的延迟,这个先去掉，因为有可能客户端卡，这段时间，他的消息会卡在一起发送过来.
	////两判断两个点之间的距离，这个是用于防客户端改目标点,容错1秒走的距离
	//if (distance > 0.5 && ((interverTimeSec < 0.165) || (distance - interverTimeSec * m_pMaster->GetSpeed() > m_pMaster->GetSpeed()) || (fSpeed > 0 && (fSpeed - m_pMaster->GetSpeed()) > 0.1)))
	//{
	//	//传回前面一个点
	//	//Teleporting(curPos);
	//	LogInfoFmtPrint("MovePart::IsCanMove  cid=%lu,pos error teleport old pos distace=%f,curpos(%f,%f),dstpos(%f,%f),insterval=%f,maxdistance=%f,fspeed=%f,mpmastreSpeed=%f", m_pMaster->GetCid(), distance, m_pMaster->GetPos().x, m_pMaster->GetPos().z, msgCurPos.x, msgCurPos.z, interverTimeSec, interverTimeSec * m_pMaster->GetSpeed(), fSpeed, m_pMaster->GetSpeed());
	//	m_moveErrorNum++;
	//	return false;
	//}

	return true;
}


//void MovePart::BeenSeeMoving(void *pContext, int32_t nLen)
//{
//	if (m_enMovingFlag==enMovingFlag_None)
//		return;
//
//	ActorMove actorMove;
//	if (nLen != sizeof(uint32_t))
//		return;
//	uint64_t cid = *(uint64_t*)pContext;
//	Scene *pScene = m_pMaster->GetScene();
//	if (!pScene)
//		return;
//	Creature *pCreature = pScene->GetCreature(cid);
//	if (!pCreature)
//		return;
//
//	// MovePart * pPart=dynamic_cast<MovePart*>(pCreature->GetPart(PART_MOVE));
//
//	//Point3<float> curpos = m_pMaster->GetPos();
//	//Vector3PB *pCurPos = new Vector3PB;
//	//pCurPos->set_x(curpos.x);
//	//pCurPos->set_y(curpos.y);
//	//pCurPos->set_z(curpos.z);
//	//actorMove.set_cid(m_pMaster->GetCid());
//	//actorMove.set_allocated_currentpos(pCurPos);
//	//m_curMovePath.GetMsgPath(actorMove);
//	//actorMove.set_speed(m_curSpeed);
//	//pCreature->SendDataToClient(LOGIC_TO_CLIENT_ACTOR_MOVE, &actorMove);
//}
//被击退
bool MovePart::BeatBack(Point3<float> dstPos)
{
	if (m_pMaster->HasBuffStateNoMove())
	{
		return false;
	}
	m_pMaster->SetPos(dstPos);
	ActorMove moveData;
	moveData.set_cid(m_pMaster->GetCid());
	Vector3PB *pCurPos = new Vector3PB;
	pCurPos->set_x(dstPos.x);
	pCurPos->set_y(dstPos.y);
	pCurPos->set_z(dstPos.z);
	moveData.set_allocated_currentpos(pCurPos);
	return m_pMaster->BroadCastData(LOGIC_TO_CLIENT_ACTOR_BEAT_BACK, &moveData, true);
}

bool MovePart::IsMoving() const
{
	if (m_enMovingFlag == enMovingFlag_None)
	{
		return false;
	}
	else
		return true;
}


bool MovePart::IsRoll() const
{
	if (m_fRockType == ActorRockerMove_Type_UpRoll || m_fRockType == ActorRockerMove_Type_DownRoll)
	{
		return true;
	}
	return false;
}

enMovingFlag MovePart::GetMoveFlag()
{
	return m_enMovingFlag;
}

bool MovePart::IsCanMoveSpeed(float sendSpeed)
{
	//速度不一致，不让走
	if (m_pMaster->CreatureKind() != CREATURE_PET && m_pMaster->GetAttr(C_TEAM_ID) <= 0)
	{
		if (m_pMaster->GetCanBeSeenFlag()==false ||  sendSpeed - m_pMaster->GetSpeed() > 0.01)
		{
			LogErrFmtPrint("client speed error! or can not beseen flag=%d , cid=%llu,movedata.speed=%f,player.speed=%f",m_pMaster->GetCanBeSeenFlag(), m_pMaster->GetCid(), sendSpeed, m_pMaster->GetSpeed());
			return false;
		}



	}

	return true;
}

//设置组队跟随状态
void MovePart::SetTeamFollowFlag(bool bFlag, float teamSpeed)
{
	if (bFlag == true)
	{
		m_moveSpeed = teamSpeed;
	}
	else
	{
		m_moveSpeed = m_pMaster->GetSpeed();
	}

	m_isTeamFollow = bFlag;
}
